#ifndef RAY_TRACE_PRO_RAY_TRACE_SYSTEM_H
#define RAY_TRACE_PRO_RAY_TRACE_SYSTEM_H

#include "Basic/GxLibBasic.h"
#include "VectorMath.h"

namespace RayTracePro
{
	using namespace GxLibMath;

	class ShaderRegistry;
	class ShadingNode;
	class Scene;
	class TextureData;
	class DifferentialGeometry;
	class Ray;
	class RayDifferential;
	class Light;
	class Material;
	class Renderer;

	class RayTraceSystem : public GxLibBasic::Object
	{
	public:
		int ImportonResolution;
		int TraceDepth;
		int TotalPhotons;
		int PhotonsPerEstimate;
		int PhotonTraceDepth;
		int FinalGatherRays;
		bool EnableFinalGather;
		int TlsId;
		float ShadowBias;
		bool DebugPrint;
		bool EnableGI;
		Vec3 AmbientLight;
		enum TextureFilterMode
		{
			TextureFilterLinear, TextureFilterTrilinear, TextureFilterAnisotropic
		} TextureFilter;
		int TextureFilterAnisotropicRate;
		virtual ShaderRegistry * GetShaderRegistry() = 0;
		virtual ShadingNode * CreateShader(const wchar_t * name) = 0;
		virtual Scene * CreateScene() = 0;
		virtual Material * CreateMaterial() = 0;
		virtual Renderer * CreateRenderer() = 0;
		virtual TextureData * LoadTexture(const wchar_t * fileName) = 0;
		virtual void FreeTexture(TextureData * texture) = 0;
	};

	class ISceneProvider
	{
	public:
		virtual Material * CreateMaterial() = 0;
		virtual Light * CreateLight() = 0;
		virtual void ClearLights() = 0;
		virtual void UpdateAccelerateStructure(int maxDepth) = 0;
		virtual void GetLights(const GxLibMath::Vec3 & position, Light **& lights, int & count) = 0;
		virtual bool TraceRay(DifferentialGeometry & inter, const Ray & ray, const RayDifferential & diffIn, float & t) = 0;
		virtual bool TraceRayPred(float & t, const Ray & ray) = 0;	
	};

	RayTraceSystem * CreateRayTraceSystem();
	void FreeRayTraceSystem(RayTraceSystem * system);
	static inline int DetectCpuCount()
	{
		SYSTEM_INFO si;
		GetSystemInfo(&si);
		return static_cast<int>(si.dwNumberOfProcessors);
	}
}

#endif